home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Tcl-Tk 8.0 / Pre-installed version / tcl8.0 / win / winDumpExts.c < prev   
Encoding:
C/C++ Source or Header  |  1997-08-15  |  12.7 KB  |  504 lines  |  [TEXT/CWIE]

  1. /* 
  2.  * winDumpExts.c --
  3.  * Author:   Gordon Chaffee, Scott Stanton
  4.  *
  5.  * History:  The real functionality of this file was written by
  6.  *           Matt Pietrek in 1993 in his pedump utility.  I've
  7.  *           modified it to dump the externals in a bunch of object
  8.  *           files to create a .def file.
  9.  *
  10.  * 10/12/95  Modified by Scott Stanton to support Relocatable Object Module
  11.  *         Format files for Borland C++ 4.5.
  12.  *
  13.  * Notes:    Visual C++ puts an underscore before each exported symbol.
  14.  *           This file removes them.  I don't know if this is a problem
  15.  *           this other compilers.  If _MSC_VER is defined,
  16.  *           the underscore is removed.  If not, it isn't.  To get a
  17.  *           full dump of an object file, use the -f option.  This can
  18.  *           help determine the something that may be different with a
  19.  *           compiler other than Visual C++.
  20.  *----------------------------------------------------------------------
  21.  *
  22.  * SCCS: @(#) winDumpExts.c 1.11 96/09/18 15:25:11
  23.  */
  24.  
  25. #include <windows.h>
  26. #include <stdio.h>
  27. #include <string.h>
  28. #include <process.h>
  29.  
  30. #ifdef _ALPHA_
  31. #define e_magic_number IMAGE_FILE_MACHINE_ALPHA
  32. #else
  33. #define e_magic_number IMAGE_FILE_MACHINE_I386
  34. #endif
  35.  
  36. /*
  37.  *----------------------------------------------------------------------
  38.  * GetArgcArgv --
  39.  * 
  40.  *    Break up a line into argc argv
  41.  *----------------------------------------------------------------------
  42.  */
  43. int
  44. GetArgcArgv(char *s, char **argv)
  45. {
  46.     int quote = 0;
  47.     int argc = 0;
  48.     char *bp;
  49.  
  50.     bp = s;
  51.     while (1) {
  52.     while (isspace(*bp)) {
  53.         bp++;
  54.     }
  55.     if (*bp == '\n' || *bp == '\0') {
  56.         *bp = '\0';
  57.         return argc;
  58.     }
  59.     if (*bp == '\"') {
  60.         quote = 1;
  61.         bp++;
  62.     }
  63.     argv[argc++] = bp;
  64.  
  65.     while (*bp != '\0') {
  66.         if (quote) {
  67.         if (*bp == '\"') {
  68.             quote = 0;
  69.             *bp = '\0';
  70.             bp++;
  71.             break;
  72.         }
  73.         bp++;
  74.         continue;
  75.         }
  76.         if (isspace(*bp)) {
  77.         *bp = '\0';
  78.         bp++;
  79.         break;
  80.         }
  81.         bp++;
  82.     }
  83.     }
  84. }
  85.  
  86. /*
  87.  *  The names of the first group of possible symbol table storage classes
  88.  */
  89. char * SzStorageClass1[] = {
  90.     "NULL","AUTOMATIC","EXTERNAL","STATIC","REGISTER","EXTERNAL_DEF","LABEL",
  91.     "UNDEFINED_LABEL","MEMBER_OF_STRUCT","ARGUMENT","STRUCT_TAG",
  92.     "MEMBER_OF_UNION","UNION_TAG","TYPE_DEFINITION","UNDEFINED_STATIC",
  93.     "ENUM_TAG","MEMBER_OF_ENUM","REGISTER_PARAM","BIT_FIELD"
  94. };
  95.  
  96. /*
  97.  * The names of the second group of possible symbol table storage classes
  98.  */
  99. char * SzStorageClass2[] = {
  100.     "BLOCK","FUNCTION","END_OF_STRUCT","FILE","SECTION","WEAK_EXTERNAL"
  101. };
  102.  
  103. /*
  104.  *----------------------------------------------------------------------
  105.  * GetSZStorageClass --
  106.  *
  107.  *    Given a symbol storage class value, return a descriptive
  108.  *    ASCII string
  109.  *----------------------------------------------------------------------
  110.  */
  111. PSTR
  112. GetSZStorageClass(BYTE storageClass)
  113. {
  114.     if ( storageClass <= IMAGE_SYM_CLASS_BIT_FIELD )
  115.         return SzStorageClass1[storageClass];
  116.     else if ( (storageClass >= IMAGE_SYM_CLASS_BLOCK)
  117.               && (storageClass <= IMAGE_SYM_CLASS_WEAK_EXTERNAL) )
  118.         return SzStorageClass2[storageClass-IMAGE_SYM_CLASS_BLOCK];
  119.     else
  120.         return "???";
  121. }
  122.  
  123. /*
  124.  *----------------------------------------------------------------------
  125.  * GetSectionName --
  126.  *
  127.  *    Used by DumpSymbolTable, it gives meaningful names to
  128.  *    the non-normal section number.
  129.  *
  130.  * Results:
  131.  *    A name is returned in buffer
  132.  *----------------------------------------------------------------------
  133.  */
  134. void
  135. GetSectionName(WORD section, PSTR buffer, unsigned cbBuffer)
  136. {
  137.     char tempbuffer[10];
  138.     
  139.     switch ( (SHORT)section )
  140.     {
  141.       case IMAGE_SYM_UNDEFINED: strcpy(tempbuffer, "UNDEF"); break;
  142.       case IMAGE_SYM_ABSOLUTE:  strcpy(tempbuffer, "ABS  "); break;
  143.       case IMAGE_SYM_DEBUG:      strcpy(tempbuffer, "DEBUG"); break;
  144.       default: wsprintf(tempbuffer, "%-5X", section);
  145.     }
  146.     
  147.     strncpy(buffer, tempbuffer, cbBuffer-1);
  148. }
  149.  
  150. /*
  151.  *----------------------------------------------------------------------
  152.  * DumpSymbolTable --
  153.  *
  154.  *    Dumps a COFF symbol table from an EXE or OBJ.  We only use
  155.  *    it to dump tables from OBJs.
  156.  *----------------------------------------------------------------------
  157.  */
  158. void
  159. DumpSymbolTable(PIMAGE_SYMBOL pSymbolTable, FILE *fout, unsigned cSymbols)
  160. {
  161.     unsigned i;
  162.     PSTR stringTable;
  163.     char sectionName[10];
  164.     
  165.     fprintf(fout, "Symbol Table - %X entries  (* = auxillary symbol)\n",
  166.         cSymbols);
  167.  
  168.     fprintf(fout, 
  169.      "Indx Name                 Value    Section    cAux  Type    Storage\n"
  170.      "---- -------------------- -------- ---------- ----- ------- --------\n");
  171.  
  172.     /*
  173.      * The string table apparently starts right after the symbol table
  174.      */
  175.     stringTable = (PSTR)&pSymbolTable[cSymbols]; 
  176.         
  177.     for ( i=0; i < cSymbols; i++ ) {
  178.     fprintf(fout, "%04X ", i);
  179.     if ( pSymbolTable->N.Name.Short != 0 )
  180.         fprintf(fout, "%-20.8s", pSymbolTable->N.ShortName);
  181.     else
  182.         fprintf(fout, "%-20s", stringTable + pSymbolTable->N.Name.Long);
  183.  
  184.     fprintf(fout, " %08X", pSymbolTable->Value);
  185.  
  186.     GetSectionName(pSymbolTable->SectionNumber, sectionName,
  187.                sizeof(sectionName));
  188.     fprintf(fout, " sect:%s aux:%X type:%02X st:%s\n",
  189.            sectionName,
  190.            pSymbolTable->NumberOfAuxSymbols,
  191.            pSymbolTable->Type,
  192.            GetSZStorageClass(pSymbolTable->StorageClass) );
  193. #if 0
  194.     if ( pSymbolTable->NumberOfAuxSymbols )
  195.         DumpAuxSymbols(pSymbolTable);
  196. #endif
  197.  
  198.     /*
  199.      * Take into account any aux symbols
  200.      */
  201.     i += pSymbolTable->NumberOfAuxSymbols;
  202.     pSymbolTable += pSymbolTable->NumberOfAuxSymbols;
  203.     pSymbolTable++;
  204.     }
  205. }
  206.  
  207. /*
  208.  *----------------------------------------------------------------------
  209.  * DumpExternals --
  210.  *
  211.  *    Dumps a COFF symbol table from an EXE or OBJ.  We only use
  212.  *    it to dump tables from OBJs.
  213.  *----------------------------------------------------------------------
  214.  */
  215. void
  216. DumpExternals(PIMAGE_SYMBOL pSymbolTable, FILE *fout, unsigned cSymbols)
  217. {
  218.     unsigned i;
  219.     PSTR stringTable;
  220.     char *s, *f;
  221.     char symbol[1024];
  222.     
  223.     /*
  224.      * The string table apparently starts right after the symbol table
  225.      */
  226.     stringTable = (PSTR)&pSymbolTable[cSymbols]; 
  227.         
  228.     for ( i=0; i < cSymbols; i++ ) {
  229.     if (pSymbolTable->SectionNumber > 0 && pSymbolTable->Type == 0x20) {
  230.         if (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) {
  231.         if (pSymbolTable->N.Name.Short != 0) {
  232.             strncpy(symbol, pSymbolTable->N.ShortName, 8);
  233.             symbol[8] = 0;
  234.         } else {
  235.             s = stringTable + pSymbolTable->N.Name.Long;
  236.             strcpy(symbol, s);
  237.         }
  238.         s = symbol;
  239.         f = strchr(s, '@');
  240.         if (f) {
  241.             *f = 0;
  242.         }
  243. #if defined(_MSC_VER) && defined(_X86_)
  244.         if (symbol[0] == '_') {
  245.             s = &symbol[1];
  246.         }
  247. #endif
  248.         if ((stricmp(s, "DllEntryPoint") != 0) 
  249.             && (stricmp(s, "DllMain") != 0)) {
  250.             fprintf(fout, "\t%s\n", s);
  251.         }
  252.         }
  253.     }
  254.  
  255.     /*
  256.      * Take into account any aux symbols
  257.      */
  258.     i += pSymbolTable->NumberOfAuxSymbols;
  259.     pSymbolTable += pSymbolTable->NumberOfAuxSymbols;
  260.     pSymbolTable++;
  261.     }
  262. }
  263.  
  264. /*
  265.  *----------------------------------------------------------------------
  266.  * DumpObjFile --
  267.  *
  268.  *    Dump an object file--either a full listing or just the exported
  269.  *    symbols.
  270.  *----------------------------------------------------------------------
  271.  */
  272. void
  273. DumpObjFile(PIMAGE_FILE_HEADER pImageFileHeader, FILE *fout, int full)
  274. {
  275.     PIMAGE_SYMBOL PCOFFSymbolTable;
  276.     DWORD COFFSymbolCount;
  277.     
  278.     PCOFFSymbolTable = (PIMAGE_SYMBOL)
  279.     ((DWORD)pImageFileHeader + pImageFileHeader->PointerToSymbolTable);
  280.     COFFSymbolCount = pImageFileHeader->NumberOfSymbols;
  281.  
  282.     if (full) {
  283.     DumpSymbolTable(PCOFFSymbolTable, fout, COFFSymbolCount);
  284.     } else {
  285.     DumpExternals(PCOFFSymbolTable, fout, COFFSymbolCount);
  286.     }
  287. }
  288.  
  289. /*
  290.  *----------------------------------------------------------------------
  291.  * SkipToNextRecord --
  292.  *
  293.  *    Skip over the current ROMF record and return the type of the
  294.  *    next record.
  295.  *----------------------------------------------------------------------
  296.  */
  297.  
  298. BYTE
  299. SkipToNextRecord(BYTE **ppBuffer)
  300. {
  301.     int length;
  302.     (*ppBuffer)++;        /* Skip over the type.*/
  303.     length = *((WORD*)(*ppBuffer))++; /* Retrieve the length. */
  304.     *ppBuffer += length;    /* Skip over the rest. */
  305.     return **ppBuffer;        /* Return the type. */
  306. }
  307.  
  308. /*
  309.  *----------------------------------------------------------------------
  310.  * DumpROMFObjFile --
  311.  *
  312.  *    Dump a Relocatable Object Module Format file, displaying only
  313.  *    the exported symbols.
  314.  *----------------------------------------------------------------------
  315.  */
  316. void
  317. DumpROMFObjFile(LPVOID pBuffer, FILE *fout)
  318. {
  319.     BYTE type, length;
  320.     char symbol[1024], *s;
  321.  
  322.     while (1) {
  323.     type = SkipToNextRecord(&(BYTE*)pBuffer);
  324.     if (type == 0x90) {    /* PUBDEF */
  325.         if (((BYTE*)pBuffer)[4] != 0) {
  326.         length = ((BYTE*)pBuffer)[5];
  327.         strncpy(symbol, ((char*)pBuffer) + 6, length);
  328.         symbol[length] = '\0';
  329.         s = symbol;
  330.         if ((stricmp(s, "DllEntryPoint") != 0) 
  331.             && (stricmp(s, "DllMain") != 0)) {
  332.             if (s[0] == '_') {
  333.             s++;
  334.             fprintf(fout, "\t_%s\n\t%s=_%s\n", s, s, s);
  335.             } else {
  336.             fprintf(fout, "\t%s\n", s);
  337.             }
  338.         }
  339.         }
  340.     } else if (type == 0x8B || type == 0x8A) { /* MODEND */
  341.         break;
  342.     }
  343.     }
  344. }
  345.  
  346. /*
  347.  *----------------------------------------------------------------------
  348.  * DumpFile --
  349.  *
  350.  *    Open up a file, memory map it, and call the appropriate
  351.  *    dumping routine
  352.  *----------------------------------------------------------------------
  353.  */
  354. void
  355. DumpFile(LPSTR filename, FILE *fout, int full)
  356. {
  357.     HANDLE hFile;
  358.     HANDLE hFileMapping;
  359.     LPVOID lpFileBase;
  360.     PIMAGE_DOS_HEADER dosHeader;
  361.     
  362.     hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
  363.                OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  364.                     
  365.     if (hFile == INVALID_HANDLE_VALUE) {
  366.     fprintf(stderr, "Couldn't open file with CreateFile()\n");
  367.     return;
  368.     }
  369.  
  370.     hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
  371.     if (hFileMapping == 0) {
  372.     CloseHandle(hFile);
  373.     fprintf(stderr, "Couldn't open file mapping with CreateFileMapping()\n");
  374.     return;
  375.     }
  376.  
  377.     lpFileBase = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
  378.     if (lpFileBase == 0) {
  379.     CloseHandle(hFileMapping);
  380.     CloseHandle(hFile);
  381.     fprintf(stderr, "Couldn't map view of file with MapViewOfFile()\n");
  382.     return;
  383.     }
  384.  
  385.     dosHeader = (PIMAGE_DOS_HEADER)lpFileBase;
  386.     if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE) {
  387. #if 0
  388.     DumpExeFile( dosHeader );
  389. #else
  390.     fprintf(stderr, "File is an executable.  I don't dump those.\n");
  391.     return;
  392. #endif
  393.     }
  394.     /* Does it look like a i386 COFF OBJ file??? */
  395.     else if ((dosHeader->e_magic == e_magic_number)
  396.         && (dosHeader->e_sp == 0)) {
  397.     /*
  398.      * The two tests above aren't what they look like.  They're
  399.      * really checking for IMAGE_FILE_HEADER.Machine == i386 (0x14C)
  400.      * and IMAGE_FILE_HEADER.SizeOfOptionalHeader == 0;
  401.      */
  402.     DumpObjFile((PIMAGE_FILE_HEADER) lpFileBase, fout, full);
  403.     } else if (*((BYTE *)lpFileBase) == 0x80) {
  404.     /*
  405.      * This file looks like it might be a ROMF file.
  406.      */
  407.     DumpROMFObjFile(lpFileBase, fout);
  408.     } else {
  409.     printf("unrecognized file format\n");
  410.     }
  411.     UnmapViewOfFile(lpFileBase);
  412.     CloseHandle(hFileMapping);
  413.     CloseHandle(hFile);
  414. }
  415.  
  416. void
  417. main(int argc, char **argv)
  418. {
  419.     char *fargv[1000];
  420.     char cmdline[10000];
  421.     int i, arg;
  422.     FILE *fout;
  423.     int pos;
  424.     int full = 0;
  425.     char *outfile = NULL;
  426.  
  427.     if (argc < 3) {
  428.       Usage:
  429.     fprintf(stderr, "Usage: %s ?-o outfile? ?-f(ull)? <dllname> <object filenames> ..\n", argv[0]);
  430.     exit(1);
  431.     }
  432.  
  433.     arg = 1;
  434.     while (argv[arg][0] == '-') {
  435.     if (strcmp(argv[arg], "--") == 0) {
  436.         arg++;
  437.         break;
  438.     } else if (strcmp(argv[arg], "-f") == 0) {
  439.         full = 1;
  440.     } else if (strcmp(argv[arg], "-o") == 0) {
  441.         arg++;
  442.         if (arg == argc) {
  443.         goto Usage;
  444.         }
  445.         outfile = argv[arg];
  446.     }
  447.     arg++;
  448.     }
  449.     if (arg == argc) {
  450.     goto Usage;
  451.     }
  452.  
  453.     if (outfile) {
  454.     fout = fopen(outfile, "w+");
  455.     if (fout == NULL) {
  456.         fprintf(stderr, "Unable to open \'%s\' for writing:\n",
  457.             argv[arg]);
  458.         perror("");
  459.         exit(1);
  460.     }
  461.     } else {
  462.     fout = stdout;
  463.     }
  464.     
  465.     if (! full) {
  466.     char *dllname = argv[arg];
  467.     arg++;
  468.     if (arg == argc) {
  469.         goto Usage;
  470.     }
  471.     fprintf(fout, "LIBRARY    %s\n", dllname);
  472.     fprintf(fout, "EXETYPE WINDOWS\n");
  473.     fprintf(fout, "CODE PRELOAD MOVEABLE DISCARDABLE\n");
  474.     fprintf(fout, "DATA PRELOAD MOVEABLE MULTIPLE\n\n");
  475.     fprintf(fout, "EXPORTS\n");
  476.     }
  477.  
  478.     for (; arg < argc; arg++) {
  479.     if (argv[arg][0] == '@') {
  480.         FILE *fargs = fopen(&argv[arg][1], "r");
  481.         if (fargs == NULL) {
  482.         fprintf(stderr, "Unable to open \'%s\' for reading:\n",
  483.             argv[arg]);
  484.         perror("");
  485.         exit(1);
  486.         }
  487.         pos = 0;
  488.         for (i = 0; i < arg; i++) {
  489.         strcpy(&cmdline[pos], argv[i]);
  490.         pos += strlen(&cmdline[pos]) + 1;
  491.         fargv[i] = argv[i];
  492.         }
  493.         fgets(&cmdline[pos], sizeof(cmdline), fargs);
  494.         fprintf(stderr, "%s\n", &cmdline[pos]);
  495.         fclose(fargs);
  496.         i += GetArgcArgv(&cmdline[pos], &fargv[i]);
  497.         argc = i;
  498.         argv = fargv;
  499.     }
  500.     DumpFile(argv[arg], fout, full);
  501.     }
  502.     exit(0);
  503. }
  504.